#ifndef QUERYTREE_H
#define QUERYTREE_H

#include "enums.h"

#include <string>

using namespace std;

// forward declarations:
class SimpleQuery;

/*
    Class: QueryTree
    This is a node of the Query structure.
    The type of the query that a QueryTree node contains can be SIMPLE, UNION or INTERSECTION.
    When the type is SIMPLE, left_query_tree and right_query_tree must be NULL.
    When the type is UNION or INTERSECTION, query must be NULL.
    It is responsible of the programmer to fit this constraints.

    See also:
        SimpleQuery
        QueryType
*/
class QueryTree
{
    /* Section: public */
    public:
        /*
            Constructor: Default constructor.
            Initializes the object.
        */
        QueryTree();

        /*
            Constructor: Parametrized constructor.
            Initializes the object as an UNION or INTERSECTION query type, so type must be one of this type.

            Parameters:
                left_query_tree  -   Left query of an UNION or INTERSECTION query (NULL if type is SIMPLE).
                right_query_tree -   Right query of an UNION or INTERSECTION query (NULL if type is SIMPLE).
                type             -   Type of the query. It can't be SIMPLE.
        */
        QueryTree(QueryType type, QueryTree * left_query_tree = NULL, QueryTree * right_query_tree = NULL);

        /*
            Destructor: Default destructor
            Destroy the object.
        */
        virtual ~QueryTree();

        /*
            Constructor: Copy constructor.
            Initializes the object as a copy from other QueryTree
        */
        QueryTree(const QueryTree& other);

        /*
            Constructor: Parametrized constructor.
            Initializes the object as a SIMPLE query type, so type will be SIMPLE.

            Parameters:
                query   -   SimpleQuery to initilized with.
        */
        QueryTree(SimpleQuery * query = NULL);

        /*
            Method: GetLeftQueryTree
            Returns:
                The left query tree.
        */
        QueryTree * getLeftQueryTree() const;

        /*
            Method: GetRightQueryTree
            Returns:
                The right query tree
        */
        QueryTree * getRightQueryTree() const;

        /*
            Method: GetSimpleQuery
            Returns:
                The simple query.
        */
        SimpleQuery * getSimpleQuery() const;

        /*
            Method: GetType
            Returns:
                The type of the query.
        */
        QueryType getQueryType();

        /*
            Method: SetLeftQueryTree
            Sets the left query tree.

            Parameters:
                query-   QueryTree to set as left query tree.
        */
        void setLeftQueryTree(QueryTree * query);

        /*
            Method: SetRightQueryTree
            Sets the right qery tree.

            Parameters:
                query   -   QueryTree to set as the right query tree.

        */
        void setRightQueryTree(QueryTree * query);

        /*
            Method: SetSimpleQuery
            Sets the simple query.
        */
        void setSimpleQuery(SimpleQuery * query);

        /*
            Method: SetType
            Sets the type of the query.

            Parameters:
                type - Type of the query.
        */
        void setType(QueryType type);

        /*
            Method: ToString
            Returns:
                A string representation of the query tree.
        */
        string toString();

        /*
            Method: clone
            Returns:
                A clone of this object.
        */
        QueryTree * clone();

    /* Section: private */
    private:
        /*
            Variable: left_query_tree
            Type: QueryTree
        */
        QueryTree * left_query_tree;

        /*
            Variable: right_query_type
            Type: QueryTree
        */
        QueryTree * right_query_tree;

        /*
            Variable: query
            Type: SimpleQuery
        */
        SimpleQuery * query;

        /*
            Variable: type
            Type: QueryType
        */
        QueryType type;
};

#endif // QUERYTREE_H
